package com.blue.Impl.author;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blue.common.constant.CommonConstant;
import com.blue.common.utils.ConvertUtils;
import com.blue.dto.author.MenuDTO;
import com.blue.dto.author.RoleDTO;
import com.blue.mapper.author.MenuMapper;
import com.blue.po.author.MenuPO;
import com.blue.po.author.RoleMenuPO;
import com.blue.service.author.IMenuService;
import com.blue.vo.author.MenuVO;
import com.github.yulichang.query.MPJQueryWrapper;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, MenuPO> implements IMenuService {

    @Override
    public List<MenuVO> menuList(String roleId) {
        List<MenuPO> menuPOS;
        if (StringUtils.isBlank(roleId)) {
            menuPOS = list();
        } else {
            MPJLambdaWrapper<MenuPO> queryWrapper = JoinWrappers.lambda(MenuPO.class)
                    .selectAll(MenuPO.class)
                    .leftJoin(RoleMenuPO.class, RoleMenuPO::getMenuId, MenuPO::getMenuId)
                    .eq(RoleMenuPO::getRoleId, roleId)
                    .ne(MenuPO::getType, CommonConstant.BUTTON);
            menuPOS = list(queryWrapper);
        }
        List<MenuVO> authorMenuVOS = ConvertUtils.convertList(MenuVO.class, menuPOS);
        //组装树结构
        List<MenuVO> level1Menus = authorMenuVOS.stream().filter(item -> CommonConstant.ROOT.equals(item.getParentId())).toList();
        return level1Menus.stream()
                .peek(level1Menu -> level1Menu.setChildren(CollectionUtils.isEmpty(getChildren(level1Menu, authorMenuVOS)) ? null : getChildren(level1Menu, authorMenuVOS)))
                .sorted((item1, item2) -> (item1.getSort() == null ? BigDecimal.ZERO : item1.getSort()).compareTo(item2.getSort() == null ? BigDecimal.ZERO : item2.getSort()))
                .collect(Collectors.toList());
    }

    private List<MenuVO> getChildren(MenuVO root, List<MenuVO> allMenuVO) {
        return allMenuVO.stream()
                .filter(item -> item.getParentId().equals(root.getMenuId()))
                .peek(item -> item.setChildren(CollectionUtils.isEmpty(getChildren(item, allMenuVO)) ? null : getChildren(item, allMenuVO)))
                .sorted((item1, item2) -> (item1.getSort() == null ? BigDecimal.ZERO : item1.getSort()).compareTo(item2.getSort() == null ? BigDecimal.ZERO : item2.getSort()))
                .collect(Collectors.toList());
    }

    @Override
    public List<MenuVO> queryMenu(MenuDTO requestDTO) {
        MPJLambdaWrapper<MenuPO> queryWrapper = JoinWrappers.lambda(MenuPO.class)
                .select(MenuPO::getPath, MenuPO::getTitle)
                .leftJoin(RoleMenuPO.class, RoleMenuPO::getMenuId, MenuPO::getMenuId)
                .like(StringUtils.isNotBlank(requestDTO.getTitle()), MenuPO::getTitle, requestDTO.getTitle())
                .eq(RoleMenuPO::getRoleId,requestDTO.getRoleId())
                .ne(MenuPO::getType, CommonConstant.BUTTON)
                .ne(MenuPO::getType, CommonConstant.CATALOG);
        List<MenuPO> menuPOS = list(queryWrapper);
        return ConvertUtils.convertList(MenuVO.class, menuPOS);
    }

    @Override
    public Map<String, List<String>> authorMenuList(RoleDTO requestDTO) {
        Map<String, List<String>> resultMap = new HashMap<>();
        MPJLambdaWrapper<MenuPO> queryWrapper = JoinWrappers.lambda(MenuPO.class)
                .select(MenuPO::getMenuId, MenuPO::getType, MenuPO::getParentId)
                .leftJoin(RoleMenuPO.class, RoleMenuPO::getMenuId, MenuPO::getMenuId)
                .eq(RoleMenuPO::getRoleId, requestDTO.getRoleId());
        List<MenuPO> menuList = this.list(queryWrapper);
        List<String> parentIds = menuList.stream().map(MenuPO::getParentId).toList();
        resultMap.put("defaultExpandedKey",
                menuList.stream().map(MenuPO::getMenuId)
                        .filter(parentIds::contains).collect(Collectors.toList()));
        resultMap.put("defaultCheckedKey",
                menuList.stream().map(MenuPO::getMenuId).collect(Collectors.toList()));
        return resultMap;
    }
}
